import axios from 'axios'
import to from '@/utils/awaitTo'
import bigInt from 'json-bigint'
// 21.6 拦截
// import Notify from '@/ui/Notify'
import store from '@/store'
// import router from '@/router'
// import { removeStorage } from '@/utils/storage'
import { refreshTokenAPI } from '@/api'

const axios2 = axios.create({
  // 项目基础地址
  baseURL: 'http://toutiao-app.itheima.net',

  transformResponse: [function (data) {
    // 对响应数据进行了处理(干预了axios默认处理的过程)
    // data:就是本次请求获取的数据
    // 24.2 -204后台返回的是空字符串，这句话报错了，导致进入了响应拦截器的error中
    if (data.length > 0) {
      return bigInt.parse(data)
    }
  }]
})

// 21.6 axios的拦截器使用
//      添加请求拦截器 -- axios之前
axios2.interceptors.request.use(function (config) {
  // 不是登录接口时，才拼接请求头---写完后api里具体的headers都不要写
  // console.log(config)
  if (config.url !== '/v1_0/authorizations') {
    config.headers.Authorization = 'Bearer ' + store.state.user.token
  }

  // 在发送请求之前做些什么
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})

// 添加响应拦截器 - 拿到了后台响应的数据(在逻辑页面执行之前)
axios2.interceptors.response.use(function (response) { // 本次axios请求的http响应状态码为2xx/3xx进这里
  // 对响应数据做点什么
  return response
}, async function (error) { // http报错4xx/5xx进入这里
  // 需求：在响应拦截器“统一”处理错误状态码
  console.dir(error)
  // 👉注：401写在此处，是因为后台返回的，不是随便写的
  if (error && error.response && error.response.status === 401) {
    // Notify({ type: 'danger', message: '用户身份已经过期，请重新登录' })

    // setTimeout(() => {
    //   removeStorage('token')// 清空本地token
    //   // 清除vuex里的token(因为开了命名空间，没有辅助函数就写成命名空间+路径的形式)
    //   store.commit('user/setToken', null) // 清空vuex里的token
    //   router.replace('/login')
    // }, 1500)

    // 方案2：用户无感知的刷新token
    // 为啥刷新需要一个额外的refresh_token(还得告诉后台你是谁)
    const [, res] = await refreshTokenAPI()
    store.commit('user/setToken', res.data.data.token) // 把新的token保存到vuex, 而且vuex的mutations函数内还同步到本地
    // return阻止代码往下走
    // axios2()再重新进行一次axios请求
    // error.config - 原来的配置
    return axios2(error.config)

    // 问题：正常请求--过期token--后台响应401--响应拦截器判断401(你只是拿到一个token保存到本地了)--返回错误提示
  }
  // 对相应其错误做点什么
  return Promise.reject(error) // 相当于reject()
})

export default ({ url, method = 'GET', data = {}, params = {}, headers = {} }) =>
// 自定义函数要返回Promise对象中，箭头函数后的大括号{}去掉，因为没写return
  to(axios2({
    url: url,
    method: method,
    params: params,
    data: data,
    headers: headers
  }))

// import request from '@/utils/request'
// request({
//     url:"请求地址",
//     method:"请求方式",
//     params:{},
//     data:{},
//     header:{}
// })
// 函数形参的对象解构赋值
// 以后如果换网络请求的库, 只需更换这里的axios,在导出的自定义函数中把传入的几个形参的值，放到新的请求库响应的参数上。保证代码的复用性和独立性(高内聚低耦合)
// $ajax({
//   url:url,
//   method:method,
//   params:params,
//   data:data,
//   headers:headers
// })
